<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>openAI</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
</head>

<body>
    <div class="container-fluid">
        <nav class="navbar bg-dark" data-bs-theme="dark">
            <div class="container-fluid">
                <a class="navbar-brand" href="#">
                    openAI
                </a>
            </div>
        </nav>
        <div style="margin-bottom: 20px"></div>
        <div class="input-group mb-3" style="margin-bottom: 10px">
            <input type="text" class="form-control" aria-label="输入问题" name="msg" placeholder="输入问题"
                aria-describedby="button-addon2">
            <button id="sendBtn" class="btn btn-outline-secondary" type="button">发送</button>
            <img src="https://img0.baidu.com/it/u=3092244791,3912704690&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500"
                alt="" class="img" onmousedown="record()" onmouseup="stopRecord()">
        </div>
        <div id="msgList"></div>
        <!-- <button onclick="record()" class="niceButton">开始录音</button>
        <button onclick="stopRecord()" class="niceButton">停止录音</button> -->
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-/mhDoLbDldZc3qpsJHpLogda//BVZbgYuw6kof4u2FrCedxOtgRZDTHgHUhOCVim"
        crossorigin="anonymous"></script>
    <script src="https://cdn.staticfile.org/jquery/3.6.3/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/jquery/3.6.3/jquery.min.map"></script>
</body>

</html>
<script type="application/javascript">
    $(function () {
        init()
    });

    function init() {
        sendMsg();
        registerKey();
    }

    function registerKey() {
        $("body").keydown(function (event) {
            const sendBtnControl = $("#sendBtn")
            // keyCode=13是回车键
            if (event.keyCode == "13") {
                // 触发 登录按钮被点击的事件
                $("#sendBtn").click();
            }
        });
    }

    function sendMsg() {
        if (window.EventSource == null) {
            alert('The browser does not support Server-Sent Events');
            return
        }

        const msgControl = $('input[type=text]')
        const sendBtnControl = $("#sendBtn")
        const msgList = $('#msgList')
        sendBtnControl.on('click', function () {
            if (msgControl.val() == "") {
                alert("请输入问题");
                return false;
            }
            let msg = msgControl.val();
            $.ajax({
                type: "post",        // 请求方式
                url: "chat", // 请求路径
                dataType: "json",   // 预期返回一个 json 类型数据
                data: { msg: msg },
                beforeSend: function () {
                    sendBtnControl.text("loading...").attr("disabled", true)
                    msgCard(0, msg)
                    msgList.prepend('<div class="alert alert-success" role="alert"><pre>' + "AI：..." + '</pre></div>')
                },
                success: function (res) {
                    console.log(res);
                    // if (res && res.code === 0) {
                    //     msgCard(1, res.msg)
                    // } else {
                    //     alert(res.msg)
                    // }
                    relyStream()
                },
                error: function (error) {
                    sendBtnControl.text("发送").attr("disabled", false)
                    msgControl.val("")
                    console.log(error)
                },
                complete: function () {
                    sendBtnControl.text("发送").attr("disabled", false)
                    msgControl.val("")
                }
            });
        })
    }

    function relyStream() {
        const url = "sse";
        // withCredentials 发送Cookie数据
        var source = new EventSource(url, { withCredentials: true });
        //建立连接
        source.onopen = function (event) {
            console.log("建立连接", event)
        }
        // 客户端接收服务器发送来的数据
        source.onmessage = function (event) {
            const msgList = $('#msgList')
            console.log(event.data);
            let msg = msgList.children().eq(0).find('pre').text()
            msgList.children().eq(0).find('pre').text(msg + event.data)
            if (event.data.endsWith("\n.end")) {
                source.close()
                console.log('connection is closed');
            }
        };
        // 发送通信错误
        source.onerror = function (event) {
            // handle error event
            console.log("通信错误", event)
        };
    }


    let mediaRecorder = null;

    // 首先打开麦克风
    function record() {
        document.querySelector(".img").src = "https://bpic.51yuansu.com/pic2/cover/00/47/09/5815a19b9bc2e_610.jpg"
        const constraints = { audio: true };
        navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
            let chunks = [];
            let options = {
                mimeType: "audio/webm",
            }
            mediaRecorder = new MediaRecorder(stream, options);
            mediaRecorder.start();

            // 录音开始事件监听（即调用 mediaRecorder.start()时会触发该事件）
            mediaRecorder.onstart = () => {
                console.log("record start");
            };

            // 录音可用事件监听，发生于mediaRecorder.stop()调用后，mediaRecorder.onstop 前
            mediaRecorder.ondataavailable = (e) => {
                console.log("dataavailable");
                console.log(e);
                chunks.push(e.data);
            };

            // 录音结束事件监听，发生在mediaRecorder.stop()和 mediaRecorder.ondataavailable 调用后
            mediaRecorder.onstop = () => {
                console.log("record end");
                // 获取到录音的blob
                let blob = new Blob(chunks, { type: "audio/mpeg;codecs=opus" });
                uploadBlob(blob)
                // 上传二进制大对象数据

                // // 创建一个blob的对象，把Json转化为字符串作为我们的值
                // let url = window.URL.createObjectURL(blob);
                // // 上面这个是创建一个blob的对象连链接，
                // // 然后创建一个链接元素，是属于 a 标签的链接元素，所以括号里才是a，
                // let link = document.createElement("a");
                // link.href = url;
                // // 把上面获得的blob的对象链接赋值给新创建的这个 a 链接
                // link.setAttribute("download", "录音.mp3");
                // // 设置下载的属性（所以使用的是download），这个是a 标签的一个属性
                // // 后面的是文件名字，可以更改
                // link.click();
            };
        }).catch(error => {
            console.error("麦克风配置加载异常：" + error);
        });
    }

    // 录音结束事件，在需要结束录音时调用，录音结束后的操作请在 mediaRecorder.onstop 里面写
    function stopRecord() {
        document.querySelector(".img").src = "https://img0.baidu.com/it/u=3092244791,3912704690&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500"
        mediaRecorder && mediaRecorder.stop();
    }

    function msgCard(type, msg) {
        const msgList = $('#msgList')
        let msgDom = null;
        if (type === 0) {
            msgDom = '<div class="alert alert-secondary" role="alert"><pre>' + "ME：" + msg + '</pre></div>'
            msgList.prepend(msgDom)
        } else {
            msgList.children().eq(0).find('pre').text("AI：" + msg)
        }
    }

    // 上传音频文件
    function uploadBlob(videoBlob) {
        var formData = new FormData();
        formData.append("file", videoBlob)
        $.ajax({
            type: 'POST',
            url: "video", // 请求路径
            contentType: false,
            processData: false,
            cache: false,
            data: formData,
            beforeSend: function () {
                console.log("发送音频数据")
            },
            success: function (res) {
                console.log("请求结果", res);
                if (res) {
                    const msgControl = $('input[type=text]')
                    msgControl.val(res.msg)
                    //触发事件
                    $('#sendBtn').click();
                } else {
                    alert("无法获取数据")
                }

            },
            error: function (err) {
                console.error("网络请求异常", err);
            },
            complete: function () {
                console.log("网络请求完成")
            }
        });
    }


</script>
<style type="text/css">
    pre {
        margin-bottom: 0;
        white-space: pre-wrap;
        /* css-3 */
        white-space: -moz-pre-wrap;
        /* Mozilla, since 1999 */
        white-space: -pre-wrap;
        /* Opera 4-6 */
        white-space: -o-pre-wrap;
        /* Opera 7 */
        word-wrap: break-word;
        /* Internet Explorer 5.5+ */
    }

    .img {
        display: inline-block;
        width: 40px;
        height: 40px;
    }
</style>